﻿using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using Lbb.Dynamic;
using Lbb.Web.Mvc.Localization;

namespace Lbb.Web.Mvc
{
    /// <summary>
    /// 数据列表模型
    /// </summary>
    /// <author>Chiron</author>
    public class DataList
    {
        #region Ctors
        public DataList()
        {
            RouteValues = new DynamicDictionary(routeValues);
        }
        #endregion Ctors

        #region Fields
        /// <summary>
        /// 总记录数
        /// </summary>
        public int Total;

        public string navigationClothes = "<ul>{0}</ul>";
        public string navigationItemClothes = "<li class='{1}'>{0}</li>";
        public string navigationItemelSectedClothes = "<span class='selected'>{0}</span>";
        #endregion Fields

        #region Props
        /// <summary>
        /// 当前页的标识(键)
        /// </summary>
        public virtual string CurrentPageKey
        {
            get
            {
                return _curPageKey;
            }
            set
            {
                _curPageKey = string.IsNullOrWhiteSpace(value) ? "p" : value;
            }
        }
        private string _curPageKey = "p";
        /// <summary>
        /// 页大小的标识(键)
        /// </summary>
        public virtual string PageSizeKey
        {
            get
            {
                return _pageSizeKey;
            }
            set
            {
                _pageSizeKey = string.IsNullOrWhiteSpace(value) ? "ps" : value;
            }
        }
        private string _pageSizeKey = "ps";
        /// <summary>
        /// 数据集。
        /// </summary>
        public virtual IEnumerable<object> Items { get; set; }
        /// <summary>
        /// 路由参数。
        /// </summary>
        public RouteValueDictionary RouteValueData
        {
            get
            {
                return routeValues;
            }
            set
            {
                routeValues = value;
                RouteValues = new DynamicDictionary(routeValues);
            }
        }
        private RouteValueDictionary routeValues = new RouteValueDictionary();
        /// <summary>
        /// 路由参数
        /// </summary>
        public dynamic RouteValues { get; private set; }

        /// <summary>
        /// 排序
        /// </summary>
        public virtual string OrderBy
        {
            get
            {
                return RouteValues.ob as string;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    routeValues.Remove("ob");
                }
                else
                {
                    RouteValues.ob = value;
                }
            }
        }
        /// <summary>
        /// 当前页
        /// </summary>
        public int CurrentPage
        {
            get { return currentPage; }
            set { currentPage = value < 1 ? 1 : value; }
        }
        private int currentPage = 1;

        /// <summary>
        /// 总页数
        /// </summary>
        public int TotalPage
        {
            get
            {
                if (Total > 0)
                {
                    if (Total % PageSize != 0)   //当Total不能被PageSize整除时，总页数加一
                        return Total / PageSize + 1;
                    else   //当Total能被PageSize整除时，直接返回页数
                    {
                        return Total / PageSize;
                    }
                }
                else
                {
                    return 0;
                }
            }
        }

        /// <summary>
        /// 记录开始位置
        /// </summary>
        public int FromIndex
        {
            get
            {
                if (CurrentPage <= 0)
                {
                    return 0;
                }
                else
                {
                    int index = PageSize * (CurrentPage - 1);
                    if (Total != 0 && index > Total)
                    {
                        index = Total;
                    }
                    return index;
                }
            }
        }

        /// <summary>
        /// 记录结束位置
        /// </summary>
        public int ToIndex
        {
            get
            {
                int index = FromIndex + PageSize;
                if (FromIndex + PageSize > Total)
                {
                    index = Total;
                }
                return index;
            }
        }

        /// <summary>
        /// 页大小
        /// </summary>
        public virtual int PageSize
        {
            get
            {
                return RouteValueData[PageSizeKey] as int? ?? 15;
            }
            set
            {
                if (value > 0)
                {
                    RouteValueData[PageSizeKey] = value < 1 || value > 500 ? 15 : value;
                }
            }
        }

        /// <summary>
        /// 关键字
        /// </summary>
        public virtual string Keyword
        {
            get
            {
                return (RouteValues.k as string ?? string.Empty).Trim();
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    routeValues.Remove("k");
                }
                else
                {
                    RouteValues.k = value;
                }
            }
        }

        /// <summary>
        /// 显示导航
        /// </summary>
        public virtual bool ShowPagination
        {
            get
            {
                return RouteValues.sp ?? true;
            }
            set
            {
                RouteValues.sp = value;
            }
        }

        /// <summary>
        /// 附加在导航参数名称前的标识符
        /// </summary>
        /// chiron  2011-8-3
        public string Flag { get; set; }
        #endregion Props

        #region Methods

        #region Helpers
        /// <summary>
        /// 整理路径参数
        /// </summary>
        /// <returns></returns>
        protected RouteValueDictionary NeatenRouteValues(RouteValueDictionary routeValues = null)
        {
            if (routeValues == null) routeValues = this.routeValues;
            if (!string.IsNullOrEmpty(Flag))
            {
                var tRVs = new RouteValueDictionary();

                foreach (var d in routeValues)
                {
                    if (!d.Key.StartsWith(Flag, StringComparison.CurrentCultureIgnoreCase))
                    {
                        tRVs.Add(Flag + d.Key, d.Value);
                    }
                    else
                    {
                        tRVs.Add(d.Key, d.Value);
                    }
                }
                routeValues = tRVs;
            }
            return routeValues;
        }
        protected RouteValueDictionary GetUniteRouteValues(object routeValues, object sourceRouteValues = null)
        {
            var rvs = new RouteValueDictionary();
            var srv = sourceRouteValues ?? this.routeValues;
            if (srv is IDictionary<string, object>)
            {
                foreach (var item in srv as IDictionary<string, object>)
                {
                    rvs[item.Key] = item.Value;
                }
            }
            else
            {
                Type t = srv.GetType();
                foreach (var pi in t.GetProperties())
                {
                    try
                    {
                        rvs[pi.Name] = pi.GetValue(srv, null);
                    }
                    catch { }
                }
            }

            if (routeValues == null) return rvs;

            if (routeValues is IDictionary<string, object>)
            {
                foreach (var item in routeValues as IDictionary<string, object>)
                {
                    rvs[item.Key] = item.Value;
                }
            }
            else
            {
                Type t = routeValues.GetType();
                foreach (var pi in t.GetProperties())
                {
                    try
                    {
                        rvs[pi.Name] = pi.GetValue(routeValues, null);
                    }
                    catch { }
                }
            }
            return rvs;
        }
        #endregion Helpers

        public virtual string PageToString()
        {
            if (TotalPage == 0)
            {
                return DataListRes.NoData;
            }
            return string.Format(DataListRes.PageToString, CurrentPage, TotalPage);
        }

        /// <summary>
        /// 显示当前显示的记录范围.
        /// </summary>
        /// <param name="showNoData">当没有记录时显示没有记录的提示.</param>
        /// <returns></returns>
        /// chiron  2011-6-25
        public virtual string ItemToString(bool showNoData = false)
        {
            if (TotalPage == 0)
            {
                return showNoData ? DataListRes.NoData : string.Empty;
            }
            if (TotalPage == 1)
            {
                return string.Empty;
            }
            return string.Format(DataListRes.ItemToString, FromIndex + 1, ToIndex);
        }

        #region TextPageNavigation
        public virtual MvcHtmlString TextPageNavigation(HtmlHelper html, string actionName, string controllerName, string liClassName, object routeValues)
        {
            if (!ShowPagination || TotalPage < 2) return null;

            var rvs = RouteValueData;

            string rv = "";

            if (CurrentPage > 1)
            {
                #region 首页
                RouteValueData[CurrentPageKey] = 1;
                rv = string.Format(navigationItemClothes, html.ActionLink(DataListRes.FirstPage, actionName, controllerName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), "") + " ";
                #endregion

                #region 上一页
                RouteValueData[CurrentPageKey] = CurrentPage - 1;
                rv += string.Format(navigationItemClothes, "<b></b>" + html.ActionLink(DataListRes.PreviousPage, actionName, controllerName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), "prev") + " ";
                #endregion
            }

            #region 数字导航
            var startPage = TotalPage > 8 && CurrentPage > 5 ? CurrentPage - 4 : 1;
            var endPage = startPage + 7;
            if (endPage > TotalPage) endPage = TotalPage;

            for (int pn = startPage; pn <= endPage; pn++)
            {
                if (pn != CurrentPage)
                {
                    RouteValueData[CurrentPageKey] = pn;
                    rv += string.Format(navigationItemClothes, html.ActionLink(pn.ToString(), actionName, controllerName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), liClassName) + " ";
                }
                else
                {
                    rv += string.Format(navigationItemClothes, string.Format(navigationItemelSectedClothes, pn.ToString()), liClassName) + " ";
                }
            }
            #endregion

            if (CurrentPage < TotalPage)
            {
                #region 下一页
                RouteValueData[CurrentPageKey] = CurrentPage + 1;
                rv += string.Format(navigationItemClothes, html.ActionLink(DataListRes.NextPage, actionName, controllerName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString() + "<b></b>", "next") + " ";
                #endregion

                #region 末页
                RouteValueData[CurrentPageKey] = TotalPage;
                rv += string.Format(navigationItemClothes, html.ActionLink(DataListRes.LastPage, actionName, controllerName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), "");
                #endregion
            }

            return new MvcHtmlString(string.Format(navigationClothes, rv));
        }

        /// <summary>
        /// TextPageNavigation 分页参数为 p,在编写控制器就请注意！！
        /// </summary>
        public virtual MvcHtmlString TextPageNavigation(HtmlHelper html, string actionName, string controllerName, string liClassName)
        {
            return TextPageNavigation(html, actionName, controllerName, liClassName, null);
        }

        public virtual MvcHtmlString TextPageNavigation(HtmlHelper html, string actionName, string controllerName)
        {
            return TextPageNavigation(html, actionName, controllerName, null);
        }
        #endregion

        #region AjaxTextPageNavigation
        public virtual MvcHtmlString AjaxTextPageNavigation(AjaxHelper ajax, string actionName, string controllerName, object routeValues, AjaxOptions ajaxOptions, string liClassName)
        {
            if (!ShowPagination || TotalPage < 2) return null;
            RouteValues.controllerName = controllerName;
            var rvs = RouteValueData;

            string rv = "";

            if (CurrentPage > 1)
            {
                #region 首页
                RouteValueData[CurrentPageKey] = 1;
                rv = string.Format(navigationItemClothes, ajax.ActionLink(DataListRes.FirstPage, actionName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), ajaxOptions).ToHtmlString(), "first");
                #endregion

                #region 上一页
                RouteValueData[CurrentPageKey] = CurrentPage - 1;
                rv += string.Format(navigationItemClothes, ajax.ActionLink(DataListRes.PreviousPage, actionName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), ajaxOptions).ToHtmlString(), "previous");
                #endregion
            }

            #region 数据导航
            var startPage = TotalPage > 8 && CurrentPage > 5 ? CurrentPage - 4 : 1;
            var endPage = startPage + 7;
            if (endPage > TotalPage) endPage = TotalPage;

            for (int pn = startPage; pn <= endPage; pn++)
            {
                if (pn != CurrentPage)
                {
                    RouteValueData[CurrentPageKey] = pn;
                    rv += string.Format(navigationItemClothes, ajax.ActionLink(pn.ToString(), actionName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), ajaxOptions).ToHtmlString(), liClassName);
                }
                else
                {
                    rv += string.Format(navigationItemelSectedClothes, pn.ToString(), liClassName);
                }
            }
            #endregion

            if (CurrentPage < TotalPage)
            {
                #region 下一页
                RouteValueData[CurrentPageKey] = CurrentPage + 1;
                rv += string.Format(navigationItemClothes, ajax.ActionLink(DataListRes.NextPage, actionName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), ajaxOptions).ToHtmlString(), "next");
                #endregion

                #region 末页
                RouteValueData[CurrentPageKey] = TotalPage;
                rv += string.Format(navigationItemClothes, ajax.ActionLink(DataListRes.LastPage, actionName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), ajaxOptions).ToHtmlString(), "last");
                #endregion
            }

            return new MvcHtmlString(string.Format(navigationClothes, rv));
        }
        public virtual MvcHtmlString AjaxTextPageNavigation(AjaxHelper ajax, string actionName, string controllerName, AjaxOptions ajaxOptions, string liClassName)
        {
            return AjaxTextPageNavigation(ajax, actionName, controllerName, null, ajaxOptions, liClassName);
        }
        public virtual MvcHtmlString AjaxTextPageNavigation(AjaxHelper ajax, string actionName, string controllerName, AjaxOptions ajaxOptions)
        {
            return AjaxTextPageNavigation(ajax, actionName, controllerName, ajaxOptions, "");
        }

        public virtual MvcHtmlString AjaxTextPageNavigation(AjaxHelper ajax, string actionName, string controllerName, object rotueValues, AjaxOptions ajaxOptions)
        {
            return AjaxTextPageNavigation(ajax, actionName, controllerName, rotueValues, ajaxOptions, "");
        }
        public virtual MvcHtmlString AjaxTextPageNavigation(AjaxHelper ajax, string actionName, AjaxOptions ajaxOptions)
        {
            return AjaxTextPageNavigation(ajax, actionName, null as string, ajaxOptions);
        }
        public virtual MvcHtmlString AjaxTextPageNavigation(AjaxHelper ajax, string actionName, object rotueValues, AjaxOptions ajaxOptions)
        {
            return AjaxTextPageNavigation(ajax, actionName, null as string, rotueValues, ajaxOptions);
        }
        #endregion

        #region RouteTextPageNavigation
        public virtual MvcHtmlString RouteTextPageNavigation(HtmlHelper html, string routeName, object routeValues = null, string liClassName = null)
        {
            if (!ShowPagination || TotalPage < 2) return null;

            var rvs = RouteValueData;

            string rv = "";

            if (CurrentPage > 1)
            {
                #region 首页
                RouteValueData[CurrentPageKey] = 1;
                rv = string.Format(navigationItemClothes, html.RouteLink(DataListRes.FirstPage, routeName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), "") + " ";
                #endregion

                #region 上一页
                RouteValueData[CurrentPageKey] = CurrentPage - 1;
                rv += string.Format(navigationItemClothes, html.RouteLink(DataListRes.PreviousPage, routeName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), "prev") + " ";
                #endregion
            }

            #region 数字导航
            var startPage = TotalPage > 8 && CurrentPage > 5 ? CurrentPage - 4 : 1;
            var endPage = startPage + 7;
            if (endPage > TotalPage) endPage = TotalPage;

            for (int pn = startPage; pn <= endPage; pn++)
            {
                if (pn != CurrentPage)
                {
                    RouteValueData[CurrentPageKey] = pn;
                    rv += string.Format(navigationItemClothes, html.RouteLink(pn.ToString(), routeName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), liClassName) + " ";
                }
                else
                {
                    rv += string.Format(navigationItemClothes, string.Format(navigationItemelSectedClothes, pn.ToString()), liClassName) + " ";
                }
            }
            #endregion

            if (CurrentPage < TotalPage)
            {
                #region 下一页
                RouteValueData[CurrentPageKey] = CurrentPage + 1;
                rv += string.Format(navigationItemClothes, html.RouteLink(DataListRes.NextPage, routeName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString() + "<b></b>", "next") + " ";
                #endregion

                #region 末页
                RouteValueData[CurrentPageKey] = TotalPage;
                rv += string.Format(navigationItemClothes, html.RouteLink(DataListRes.LastPage, routeName, GetUniteRouteValues(NeatenRouteValues(rvs), routeValues), null).ToHtmlString(), "");
                #endregion
            }

            return new MvcHtmlString(string.Format(navigationClothes, rv));
        }

        #endregion RouteTextPageNavigation

        #endregion Methods

    }

    /// <summary>
    /// NavigationModel
    /// </summary>
    /// <typeparam name="T">类</typeparam>
    /// <author>Chiron</author>
    public class DataList<T> : DataList
    {
        #region Props
        public IEnumerable<T> Items
        {
            get
            {
                if (base.Items == null) return new List<T>();
                return base.Items as IEnumerable<T>;
            }
            set
            {
                base.Items = value as IEnumerable<object>;
            }
        }
        #endregion Props

        #region Methods
        public virtual void FillData(IEnumerable<T> data)
        {
            //if (data == null) throw new ArgumentNullException("data");
        }
        #endregion Methods
    }
}